How to work with Navigation Controller in android with Kotlin.(Part-2)
You have not read my first article related to this topic please go through by using the link mention above. For getting the basic understanding of the navigation controller.
How to implement a Navigation Drawer with Navigation Architecture component and pass the safe-arguments?
- Create an activity with a navigation drawer and a toolbar.
- Define the NavHostFragment in the layout
- Link the host fragment with a navigation graph
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<com.google.android.material.appbar.AppBarLayout
android:layout_height="wrap_content"
android:layout_width="wrap_content"
>
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark"
/>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.dashboard.MainActivity">
<fragment
android:id="@+id/my_nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:defaultNavHost="true"
app:navGraph="@navigation/my_navigation_graph"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.appbar.AppBarLayout>
<com.google.android.material.navigation.NavigationView
android:id="@+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:menu="@menu/activity_main_drawer"/>
</androidx.drawerlayout.widget.DrawerLayout>
- Create a NavController instance
lateinit var navController: NavController
- Link the NavController instance with a navigation graph
navController = Navigation.findNavController(this@MainActivity,
R.id.my_nav_host_fragment
)
- Here we need a NavigationUI class and a kotlin extension navigation-ui-ktx
- NavigationUI class have static methods which are used to navigate the menu item to destination. And navigation-ui-ktx is an extension which provides the NavigationUI class and others.
- NavigationUI provides support the following top app bar types
1. ToolBar
2. CollapsingToolbarLayout
3. ActionBar - setup the drawer layout and toolbar in MainActivity.kt
- Link the navigation drawer with navigation controller graph
val appBarConfiguration = AppBarConfiguration(navController.graph, drawer_layout)
NavigationUI.setupWithNavController(toolbar, navController, appBarConfiguration)
NavigationUI.setupActionBarWithNavController(this, navController, drawer_layout)
AppBarConfigration
Configuration options for NavigationUI methods that interact with implementations of the app bar pattern such as.
android.support.v7.widget.Toolbar,
android.support.design.widget.CollapsingToolbarLayout, and
android.support.v7.app.ActionBar.
In the above code snap, we passed the NavGraph and the drawer layout in the AppBarConfigration.
SetupWithNavController
This method uses to link toolbar with NavController. And by calling this methods toolbar title will automatically be updated on the destination changes.
the appBarConfiguration provides the controls, how the navigation button is displayed and what action will trigger when the navigation button is tabbed.
Title value will be the value defined in the graph attribute android:label
SetupActionBarWithNavController
This method used to manage the navigation drawer icon and toolbar too. The root fragment in the navigation graph considers as the top-level destination and the drawer will show on this fragment only other fragment will display a back button.
OnSuppotNavigationUp
This method used to manage the back stack when using the navigation drawer. And this method called when the user chooses to navigate up in the application
override fun onSupportNavigateUp(): Boolean {
return Navigation.findNavController(this,
R.id.my_nav_host_fragment
).navigateUp() || super.onSupportNavigateUp()
}
Safe Arguments
Navigation architecture component provides the feature called safe arguments in which you can pass the data between the destination jus adding the argument in the navigation graph.it’s have a Gradle plugin called Safe Args that generates simple object and builder classes for type-safe access to arguments specified for destinations and actions. This is the preferred way to pass data when using the navigation
How to implement?
- You just have to add a gradle dependency in the project level
def nav_version = "2.1.0-alpha06"
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
- And apply the same plugin in the app level gradle.
apply plugin: "androidx.navigation.safeargs.kotlin"
- Just add the argument in the navigation graph. you can add an argument in two way by using the graph design view and by typing in the graph XML file
<fragment android:id="@+id/forgotFragment"
....................
<argument
android:name="email"
app:argType="string"/>
</fragment>
You can see in the given image that there is a number of Data Types supported by safe-argument and you can add a default value too.
- In the fragment layout, you just have to add the below code for putting the argument value for the destination.
LoginFragmentDirections is the class generated by the safe argument dependency which helps to pass data from.
val email = mEtEmail.text.toString()
val action = LoginFragmentDirections.actionLoginFragmentToForgotFragment(email)
navController.navigate(action)
- You can also pass the data by using the bundle in the navigate method
navController.navigate(R.id.action_fragment, bundle)
Conclusion
Navigation Architecture components are very useful and easy to use and as per the google guideline, single activity with multiple fragments made application light and smooth. And this also makes the clean code architecture and manage the fragment transaction easily and also provide a graphical view of the navigation graph.
Here is the full source code of the Navigation controller